Up: Conditionals [Contents][Index]
The cond form lets you choose between
alternatives using predicate conditions that compare values of
expressions against specific values known and written in advance.
However, sometimes it is useful to select alternatives based on
more general conditions that distinguish between broad classes of
values. The pcase macro allows you to choose between
alternatives based on matching the value of an expression against
a series of patterns. A pattern can be a literal value (for
comparisons to literal values you’d use cond),
or it can be a more general description of the expected structure
of the expression’s value.
Evaluate expression and choose among an
arbitrary number of alternatives based on the value of
expression. The possible alternatives are
specified by clauses, each of which must be a list
of the form (pattern
body-forms…). pcase
tries to match the value of expression to the
pattern of each clause, in textual order. If the
value matches, the clause succeeds; pcase then
evaluates its body-forms, and returns the value of
the last of body-forms. Any remaining
clauses are ignored.
The pattern part of a clause can be of one of two types: QPattern, a pattern quoted with a backquote; or a UPattern, which is not quoted. UPatterns are simpler, so we describe them first.
Note: In the description of the patterns below, we use
“the value being matched” to refer to the value
of the expression that is the first argument of
pcase.
A UPattern can have the following forms:
'valMatches if the value being matched is
equal to val.
atomMatches any atom, which can be a keyword, a
number, or a string. (These are self-quoting, so this
kind of UPattern is actually a shorthand for
'atom.) Note that a string or a
float matches any string or float with the same
contents/value.
_Matches any value. This is known as don’t care or wildcard.
symbolMatches any value, and additionally let-binds symbol to the value it matched, so that you can later refer to it, either in the body-forms or also later in the pattern.
(pred predfun)Matches if the predicate function predfun
returns non-nil when called with the value
being matched as its argument. predfun can be
one of the possible forms described below.
(guard boolean-expression)Matches if boolean-expression evaluates to
non-nil. This allows you to include in a
UPattern boolean conditions that refer to symbols bound
to values (including the value being matched) by previous
UPatterns. Typically used inside an and
UPattern, see below. For example,
(and x (guard (< x 10)))
is a pattern which matches any number smaller than 10
and let-binds the variable x to that
number.
(let upattern
expression)Matches if the specified expression matches
the specified upattern. This allows matching a
pattern against the value of an arbitrary
expression, not just the expression that is the first
argument to pcase. (It is called
let because upattern can bind
symbols to values using the symbol UPattern.
For example:
((or `(key . ,val) (let val 5)) val).)
(app function
upattern)Matches if function applied to the value
being matched returns a value that matches
upattern. This is like the pred
UPattern, except that it tests the result against
UPattern, rather than against a boolean truth
value. The function call can use one of the
forms described below.
(or upattern1
upattern2…)Matches if one the argument UPatterns matches. As soon as the first matching UPattern is found, the rest are not tested. For this reason, if any of the UPatterns let-bind symbols to the matched value, they should all bind the same symbols.
(and upattern1
upattern2…)Matches if all the argument UPatterns match.
The function calls used in the pred and
app UPatterns can have one of the following
forms:
integerpIn this case, the named function is applied to the value being matched.
(lambda (arg)
body)In this case, the lambda-function is called with one argument, the value being matched.
(func
args…)This is a function call with n specified arguments; the function is called with these n arguments and an additional n+1-th argument that is the value being matched.
Here’s an illustrative example of using UPatterns:
(pcase (get-return-code x)
('success (message "Done!"))
('would-block (message "Sorry, can't do it now"))
('read-only (message "The shmliblick is read-only"))
('access-denied (message "You do not have the needed rights"))
(code (message "Unknown return code %S" code)))
In addition, you can use backquoted patterns that are more
powerful. They allow matching the value of the
expression that is the first argument of
pcase against specifications of its
structure. For example, you can specify that the
value must be a list of 2 elements whose first element is a
specific string and the second element is any value with a
backquoted pattern like `("first"
,second-elem).
Backquoted patterns have the form
`qpattern where qpattern
can have the following forms:
(qpattern1 .
qpattern2)Matches if the value being matched is a cons cell
whose car matches qpattern1 and
whose cdr matches qpattern2. This
readily generalizes to backquoted lists as in
(qpattern1 qpattern2 …).
[qpattern1 qpattern2
… qpatternm]Matches if the value being matched is a vector of
length m whose
0..(m-1)th elements
match qpattern1, qpattern2 …
qpatternm, respectively.
atomMatches if corresponding element of the value being
matched is equal to the specified
atom.
,upatternMatches if the corresponding element of the value being matched matches the specified upattern.
Note that uses of QPatterns can be expressed using only
UPatterns, as QPatterns are implemented on top of UPatterns
using pcase-defmacro, described below. However,
using QPatterns will in many cases lead to a more readable
code.
Here is an example of using pcase to implement a
simple interpreter for a little expression language (note that
this example requires lexical binding, see Lexical Binding):
(defun evaluate (exp env)
(pcase exp
(`(add ,x ,y) (+ (evaluate x env) (evaluate y env)))
(`(call ,fun ,arg) (funcall (evaluate fun env) (evaluate arg env)))
(`(fn ,arg ,body) (lambda (val)
(evaluate body (cons (cons arg val) env))))
((pred numberp) exp)
((pred symbolp) (cdr (assq exp env)))
(_ (error "Unknown expression %S" exp))))
Here `(add ,x ,y) is a pattern that checks that
exp is a three-element list starting with the
literal symbol add, then extracts the second and
third elements and binds them to the variables x and
y. Then it evaluates x and
y and adds the results. The call and
fn patterns similarly implement two flavors of
function calls. (pred numberp) is a pattern that
simply checks that exp is a number and if so,
evaluates it. (pred symbolp) matches symbols, and
returns their association. Finally, _ is the
catch-all pattern that matches anything, so it’s suitable
for reporting syntax errors.
Here are some sample programs in this small language, including their evaluation results:
(evaluate '(add 1 2) nil) ;=> 3 (evaluate '(add x y) '((x . 1) (y . 2))) ;=> 3 (evaluate '(call (fn x (add 1 x)) 2) nil) ;=> 3 (evaluate '(sub 1 2) nil) ;=> error
Additional UPatterns can be defined using the
pcase-defmacro macro.
Define a new kind of UPattern for pcase. The
new UPattern will be invoked as (name
actual-args). The body should
describe how to rewrite the UPattern name into
some other UPattern. The rewriting will be the result of
evaluating body in an environment where
args are bound to actual-args.
Up: Conditionals [Contents][Index]